package com.newcoin.chat.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.newcoin.chat.beans.EncoderClassVo;
import com.newcoin.chat.beans.entity.FriendMsgEntity;
import com.newcoin.chat.beans.entity.GroupMemberEntity;
import com.newcoin.chat.beans.entity.GroupMsgEntity;
import com.newcoin.chat.beans.vo.FriendOfflineMsgVo;
import com.newcoin.chat.beans.vo.GroupOfflineMsgVo;
import com.newcoin.chat.beans.vo.Message;
import com.newcoin.chat.service.ChatService;
import com.newcoin.chat.service.FriendService;
import com.newcoin.chat.service.GroupService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@ServerEndpoint(value = "/chat/{userId}", encoders = {EncoderClassVo.class})
//encoders = {EncoderClassVo.class} 添加List编码器
@Slf4j
@Component
public class ChatController {

    /**
     * 当前在线人数
     */
    private static int ON_LINE_COUNT = 0;

    private static FriendService friendService;

    private static GroupService groupService;

    private static ChatService chatService;

    @Autowired
    public void addFriendService(FriendService friendService) {
        this.friendService = friendService;
    }

    @Autowired
    public void addGroupService(GroupService groupService) {
        this.groupService = groupService;
    }

    @Autowired
    public void addChatService(ChatService chatService) {
        this.chatService = chatService;
    }

    private static CopyOnWriteArraySet<ChatController> socket = new CopyOnWriteArraySet<>();

    /**
     * userMap  用户id和Session一一对应
     */
    private static ConcurrentHashMap<Long, Session> userMap = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam("userId") Long userId) {
        log.info("socket 入参 userId={}", userId);
        try {
            //不存在则添加
            if (!this.userMap.containsKey(userId)) {
                this.userMap.put(userId, session);
            }
            this.addOnlineCount();//人数加一
            log.info("有人连接啦!!!当前在线人数：" + this.ON_LINE_COUNT);
            //判断是否有新的消息  好友邀请
            if (friendService.isThereANewFriendApplication(userId).getResultData()) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("type", "friend");
                jsonObject.put("isNewMsg", true);
                session.getBasicRemote().sendText(jsonObject.toJSONString());
            }
            if (groupService.isThereANewGroupApplication(userId).getResultData()) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("type", "group");
                jsonObject.put("isNewMsg", true);
                session.getBasicRemote().sendText(jsonObject.toJSONString());
            }
            List list = chatService.getOfflineMsg(userId);
            session.getBasicRemote().sendObject(list);
        } catch (Exception e) {
            log.error("e={}", e.getMessage());
        }


    }

    @OnClose
    public void onClose(@PathParam("userId") Long userId) {
        try {
            if (userMap.get(userId) != null && userMap.get(userId).isOpen())
                userMap.get(userId).close();
            userMap.remove(userId);
            subOnlineCount();
            log.info("有人退出啦,当前在线人数" + ON_LINE_COUNT);
            new Thread(() -> {
                //当用户退出后记录每个群的最后一条消息的id
                try {
                    groupService.getGroupMemberByUserId(userId);
                } catch (Exception e) {
                    log.info("close----用户退出后记录每个群的最后一条消息的id出错 e={}", e.getMessage());
                }
            }).start();
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    @OnMessage
    public void onMessage(String msg, @PathParam("userId") Long userId, Session session) {
        try {
            //如果不存在则添加
            if (this.userMap.get(userId) == null)
                this.userMap.put(userId, session);
            Message message = JSON.parseObject(msg, Message.class);
            switch (message.getMsgType()) {
                case "friend":
                    pushFriend(message);
                    break;
                case "group":
                    pushGroup(message);
                    break;
                case "sys_friend":
                    pushSysFriend(message);
                    break;
                case "sys_group":
                    pushSysGroup(message);
                    break;
                case "addFriend":
                    pushAddFriend(message);
                    break;
                case "addGroup":
                    pushAddGroup(message);
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    @OnError
    public void onError(Throwable throwable, @PathParam("userId") Long userId) {
        try {
            log.error("userId={}", userId, throwable);
            new Thread(() -> {
                //当用户退出后记录每个群的最后一条消息的id
                try {
                    groupService.getGroupMemberByUserId(userId);
                } catch (Exception e) {
                    log.info("error 方法 ---用户退出后记录每个群的最后一条消息的id出错 e={}", e.getMessage());
                }
            }).start();
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    /**
     * 推送给朋友
     *
     * @param message
     */
    private void pushFriend(Message message) {
        log.info("message={}", message);
        try {
            Long toUser = message.getToUser();
            FriendMsgEntity friendMsgEntity = new FriendMsgEntity();
            int unreadNum = 0;
            if (userMap.get(toUser) != null && userMap.get(toUser).isOpen()) {
                FriendOfflineMsgVo msgVo = new FriendOfflineMsgVo();
                msgVo.setFriendMsgContent(message.getContent());
                msgVo.setCrateDate(new SimpleDateFormat("yyyy-MM-dd HH:ss:mm").format(new Date()));
                msgVo.setFriendHeadImgPath(message.getFromUserHeadImgPath());
                msgVo.setFriendNickname(message.getFromUserNickname());
                msgVo.setFriendId(toUser);
                msgVo.setIsSystemType(0);
                msgVo.setIsOpenBurnDown(message.getState());
                userMap.get(toUser).getBasicRemote().sendText(JSON.toJSONString(message));
                friendMsgEntity.setIsHaveRead(1);
            } else {
                friendMsgEntity.setIsHaveRead(0);
                unreadNum++;
            }
            friendMsgEntity.setState(message.getState());
            friendMsgEntity.setContent(message.getContent());
            friendMsgEntity.setType(message.getType());
            friendMsgEntity.setToUser(toUser);
            friendMsgEntity.setFromUser(message.getFromUser());
            chatService.addFriendMsg(friendMsgEntity);
            chatService.updateFriendLastMsfInfo(toUser, message.getFromUser(), friendMsgEntity.getId(), unreadNum);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    /**
     * 推送群消息
     *
     * @param message
     */
    private void pushGroup(Message message) {
        log.info("message={}", message);
        try {
            Long groupId = message.getGroupId();
            GroupMsgEntity groupMsgEntity = new GroupMsgEntity();
            groupMsgEntity.setType(message.getType());
            groupMsgEntity.setIsSystemType(0);
            groupMsgEntity.setState(message.getState());
            groupMsgEntity.setGroupId(message.getGroupId());
            groupMsgEntity.setFromUser(message.getFromUser());
            groupMsgEntity.setContent(message.getContent());
            groupMsgEntity.setType(message.getType());
            chatService.addGroupMsg(groupMsgEntity);
            List<Long> groupMember = chatService.getGroupMember(groupId);
            log.info("groupMemberCount={}", groupMember.size());
            groupMember.forEach(u -> {
                if (!u.equals(message.getFromUser())) {
                    GroupOfflineMsgVo groupOfflineMsgVo = new GroupOfflineMsgVo();
                    groupOfflineMsgVo.setFromUser(message.getFromUser());
                    groupOfflineMsgVo.setFromNickname(message.getFromUserNickname());
                    groupOfflineMsgVo.setFromHeadImgPath(message.getFromUserHeadImgPath());
                    groupOfflineMsgVo.setGroupMsgContent(message.getContent());
                    groupOfflineMsgVo.setCrateDate(new SimpleDateFormat("yyyy-MM-dd HH:ss:mm").format(new Date()));
                    groupOfflineMsgVo.setGroupHeadImgPath(message.getGroupHeadImgPath());
                    groupOfflineMsgVo.setGroupId(groupId);
                    groupOfflineMsgVo.setGroupName(message.getGroupName());
                    groupOfflineMsgVo.setIsOpenBurnDown(message.getState());
                    groupOfflineMsgVo.setIsSystemType(0);
                    groupOfflineMsgVo.setType(message.getType());
                    log.info("groupOfflineMsgVo={}", groupOfflineMsgVo);
                    try {
                        if (userMap.get(u) != null && userMap.get(u).isOpen()) {
                            userMap.get(u).getBasicRemote().sendText(JSON.toJSONString(message));
                        } else {
                            chatService.updateGroupLastMsfInfo(message.getGroupId(), u, groupMsgEntity.getId());
                        }
                    } catch (Exception e) {
                        log.error(e.getMessage());
                    }
                }
            });
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    /**
     * 推送给朋友系统消息
     *
     * @param message
     */
    private void pushSysFriend(Message message) {
        try {
            log.info("message={}", message);
            userMap.get(message.getToUser()).getBasicRemote().sendText(JSON.toJSONString(message));
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    /**
     * 推送群系统消息
     *
     * @param message
     */
    private void pushSysGroup(Message message) {
        try {
            log.info("message={}", message);
            List<Long> groupMember = chatService.getGroupMember(message.getGroupId());
            groupMember.forEach(u -> {
                try {
                    userMap.get(u).getBasicRemote().sendText(JSON.toJSONString(message));
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            });
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    private void pushAddGroup(Message message) {
        try {
            log.info("message={}", message);
            userMap.get(message.getToUser()).getBasicRemote().sendText(JSON.toJSONString(message));
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    private void pushAddFriend(Message message) {
        try {
            log.info("message={}", message);
            userMap.get(message.getToUser()).getBasicRemote().sendText(JSON.toJSONString(message));
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    private void addOnlineCount() {
        this.ON_LINE_COUNT++;
    }

    private void subOnlineCount() {
        this.ON_LINE_COUNT--;
    }

}
